import Mesh2D from "./Mesh2D";

const { ccclass, property, menu, executeInEditMode } = cc._decorator;

@ccclass
// @executeInEditMode
@menu('cccframework/Rope')
export default class Rope extends Mesh2D {

    @property
    _jointCount: number = 5;
    @property({
        type: cc.Integer,
        tooltip: '绳子节数，节数越多效果越好'
    })
    get jointCount(): number {
        return this._jointCount;
    }
    set jointCount(v: number) {
        if (v > 0) {
            this._jointCount = v;
            this.initVertexes();
        }
    }
    points: cc.Vec2[] = [];
    get vertexesCount() {
        return (this.jointCount + 1) * 2;
    }
    isFixTail: boolean = false;

    onLoad() {
        super.onLoad && super.onLoad()
        this.spriteFrame = this.spriteFrame;
        this.initVertexes();
        console.log('vertexesCount', this.vertexesCount)
    }
    dt: number = 0;
    update(dt: number) {
        this.dt = dt;
        super.update && super.update(dt);
        this.simulate();
        this.applyConstraint();
        this.updateMeshData();
    }
    @property
    gravity: number = -9.8;
    // 更新重力、加速度
    simulate() {
        let cw = this.node.width, ch = this.node.height;
        let defaultWidth = ch / (this.points.length - 1)
        let velocity = cc.v2();
        let gravity = cc.v2(0, this.gravity * this.dt)
        for (let i = 0; i < this.points.length; i++) {
            let point = this.points[i]
            let oldPos = point['oldPos'];
            if (oldPos) {
                velocity = point.sub(oldPos).normalize().mul(0.5);
                point.addSelf(velocity)
                point.addSelf(gravity)
            }
        }
    }
    /**更新约束 */
    applyConstraint() {
        let cw = this.node.width, ch = this.node.height;
        let defaultWidth = ch / (this.points.length - 1)
        for (let k = 0; k < 20; k++) {
            // 从倒二个点开始遍历到第一个点
            if (this.points.length > 2) {
                for (let i = this.points.length - 1; i >= 1; i--) {
                    let secondPoint = this.points[i];
                    let firstPoint = this.points[i - 1];
                    // debugger
                    // console.log('secondPoint', secondPoint, i)
                    let dir = secondPoint.sub(firstPoint);
                    let dist = dir.mag();
                    let vector = cc.v2();
                    if (dist > defaultWidth) {
                        vector = dir.normalize();
                    } else if (dist < defaultWidth) {
                        vector = dir.normalize().neg();
                    } else {
                        continue;
                    }
                    let fixLen = Math.abs(dist - defaultWidth);
                    secondPoint['oldPos'] = secondPoint;
                    if (this.isFixTail && i == this.points.length - 1) {
                        vector.mulSelf(fixLen);
                        firstPoint.addSelf(vector)
                    } else if (i == 1) {
                        secondPoint.subSelf(vector.mul(fixLen))
                    } else if (i > 1) {
                        vector.mulSelf(fixLen * 0.5);
                        firstPoint.addSelf(vector)
                        secondPoint.addSelf(vector.neg())
                    }
                }
            }
        }
    }
    set TailPos(endPos: cc.Vec2) {
        this.points[this.points.length - 1] = endPos;
    }
    get TailPos(): cc.Vec2 {
        return this.points[this.points.length - 1];
    }
    /** 更新一次顶点位置和uv，后面不再改动uv */
    initVertexes() {
        let cw = this.node.width, ch = this.node.height;
        // 初始化一次顶点
        let pointCount = this.vertexesCount / 2;
        let interval = ch / this.jointCount;
        this.points = [];
        for (let i = 0; i < pointCount; i++) {
            this.points[i] = cc.v2(0, -interval * i);
        }
        this.updateVerts();
        this.updateUVs();
        // console.log('this.__uvs', this.__uvs)
        // console.log('this.__verts', this.__verts)
        this.updateIndices();
    }
    /** 每次刷新只更新顶点位置 */
    calculateMesh() {
        this.updateVerts();
    }
    /**重写更新顶点位置的方法 */
    updateVerts() {
        let cw = this.node.width, ch = this.node.height;
        let verts = this.__verts;
        let idx = 0;
        let lastPoint = cc.v2(0, -1);
        let leftPos: cc.Vec2, rightPos: cc.Vec2;
        // GameHelper.clearDraw();
        let width = cw;
        for (let i = 0; i < this.points.length; i++) {
            let p = this.points[i];
            let dir = lastPoint.sub(p);
            let radian = 90 * Math.PI / 180;
            leftPos = p.add(cc.v2(0, -width / 2).rotate(radian));
            rightPos = p.add(cc.v2(0, -width / 2).rotate(-radian));
            verts[idx++] = leftPos;
            verts[idx++] = rightPos;
            lastPoint = p;
            // let wpos1 = this.node.convertToWorldSpaceAR(leftPos);
            // let wpos2 = this.node.convertToWorldSpaceAR(rightPos);
            // let wposp = this.node.convertToWorldSpaceAR(p);
            // GameHelper.drawCircle(3, wposp);
        }
        // console.log('this.__verts', this.__verts)
    }
    /**重新计算uv */
    // updateUVs() {

    // }
    /**重新更新索引方式 */
    updateIndices() {
        let idx = 0;
        let ids = this.__indices;
        let verts = this.__verts;
        ids = [];
        for (let i = 0; i < this.points.length - 1; i++) {
            ids[idx++] = i + 0;
            ids[idx++] = i + 1;
            ids[idx++] = i + 2;

            ids[idx++] = i + 3;
            ids[idx++] = i + 1;
            ids[idx++] = i + 2;
            // console.log('ids', ids)

        }
        this.__indices = ids;
        // console.log('this.__indices', this.__indices)
    }
}
